package com.zhoug.zmui3;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewParent;

import com.zhoug.common3.utils.LogUtils;
import com.zhoug.common3.utils.StringUtils;
import com.zhoug.zmui3.utils.ZMUIUtils;

import androidx.annotation.Nullable;

/**
 * A-Z字母选择器
 * 样式如通讯录右边的
 * zmui_style_ZMUISideBar
 * <p>
 * 所在的Activity需要配置   android:windowSoftInputMode="adjustPan" 否则弹出键盘后会导致字母表变小
 *
 * @Author 35574
 * @Date 2020/8/3
 * @Description
 */
public class ZMUISideBar extends View {
    private static final String TAG = ">>>ZMUISideBar";
    private static final boolean DEBUG = false;
    private String[] ARRAY = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q"
            , "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};

    private static final String M = "M";
    private int textSize;//字母大小
    private int textColor;//字母颜色
    private int colorSelected;//字母选中时的颜色
    private int backColor;//字母选中的背景

    private int choose = -1;//选中的字母角标
    private Paint paint;
    private int letterHeight;//每个字母的高度
    private float baseLineOff = 0;//文字居中的偏移量

    private boolean autoReset = false;//抬起手指自动重置
    private Paint.FontMetrics mFontMetrics = new Paint.FontMetrics();

    private OnTouchingLetterChangedListener listener;

    public ZMUISideBar(Context context) {
        this(context, null);
    }

    public ZMUISideBar(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, R.attr.zmui_style_ZMUISideBar);
    }

    public ZMUISideBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        if (paint == null) {
            paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setStyle(Paint.Style.FILL);
            paint.setAntiAlias(true);
            paint.setTextAlign(Paint.Align.CENTER);
        }
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ZMUISideBar, defStyleAttr, R.style.zmui_style_ZMUISideBar);
        textColor = a.getColor(R.styleable.ZMUISideBar_zmui_textColor, Color.parseColor("#333333"));
        colorSelected = a.getColor(R.styleable.ZMUISideBar_zmui_colorSelected, Color.parseColor("#ff0000"));
        backColor = a.getColor(R.styleable.ZMUISideBar_zmui_backColor, ZMUIUtils.UN_USED_COLOR);
        textSize = a.getDimensionPixelOffset(R.styleable.ZMUISideBar_zmui_textSize, 0);
        autoReset = a.getBoolean(R.styleable.ZMUISideBar_zmui_autoReset, false);
        int paddingStart = a.getDimensionPixelOffset(R.styleable.ZMUISideBar_android_paddingStart, 0);
        int paddingEnd = a.getDimensionPixelOffset(R.styleable.ZMUISideBar_android_paddingEnd, 0);
        int paddingTop = a.getDimensionPixelOffset(R.styleable.ZMUISideBar_android_paddingTop, 0);
        int paddingBottom = a.getDimensionPixelOffset(R.styleable.ZMUISideBar_android_paddingBottom, 0);
        String letters = a.getString(R.styleable.ZMUISideBar_zmui_letters);
        a.recycle();
        if (!StringUtils.isNullOrEmpty(letters)) {
            letters = letters.trim();
            String[] temp = ARRAY.clone();
            ARRAY = new String[temp.length + letters.length()];
            int i = 0;
            for (; i < letters.length(); i++) {
                ARRAY[i] = String.valueOf(letters.charAt(i));
            }
            for (int ii = 0; ii < temp.length; ii++) {
                ARRAY[i + ii] = temp[ii];
            }
            if (DEBUG) {
                LogUtils.d(TAG, "ZMUISideBar:ARRAY=" + ARRAY);
            }
        }
        setPadding(paddingStart, paddingTop, paddingEnd, paddingBottom);
    }


    @Override
    protected void onDraw(Canvas canvas) {
//        paint.setColor(Color.RED);
//        canvas.drawLine(0, getPaddingTop(), getWidth(), getPaddingTop(), paint);
//        canvas.drawLine(0, getHeight() - getPaddingBottom(), getWidth(), getHeight() - getPaddingBottom(), paint);
        for (int i = 0; i < ARRAY.length; i++) {
            //画字符所在的矩形
            float top = i * letterHeight + getPaddingTop();
            float bottom = top + letterHeight;
            if (DEBUG) {
                LogUtils.d(TAG, "onDraw:baseLineOff=" + baseLineOff);
            }
            paint.setColor(textColor);
            //选中状态
            if (i == choose) {
                if (backColor != Color.TRANSPARENT && backColor != ZMUIUtils.UN_USED_COLOR) {
                    paint.setColor(backColor);
                    canvas.drawCircle(getWidth() >> 1, (top + bottom) / 2, (bottom - top) / 2, paint);
                }
                paint.setColor(colorSelected);
            }
            float baseline = (bottom + top) / 2 - baseLineOff;
            if (DEBUG) {
                LogUtils.d(TAG, "onDraw:baseline=" + baseline);
            }
            canvas.drawText(ARRAY[i], getWidth() >> 1, baseline, paint);
        }
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final int action = event.getAction();
        float newY = 0;
        int newChoose = 0;
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                requestDisallowInterceptTouchEvent(true);
            case MotionEvent.ACTION_MOVE:
                newY = event.getY();//按下时的y坐标
                newChoose = getChoose(newY);
                if (choose != newChoose) {
                    choose = newChoose;
                    invalidate();
                    if (listener != null) {
                        listener.onTouchingLetterChanged(ARRAY[choose]);
                    }
//                    Log.i(TAG, "dispatchTouchEvent: choose="+choose+","+ARRAY[choose]);
                }
                return true;
            case MotionEvent.ACTION_UP:
                if (autoReset) {
                    newY = 0;
                    choose = -1;
                    invalidate();
                }
                requestDisallowInterceptTouchEvent(false);
                return false;
        }


        return true;
    }

    /**
     * 禁止父类拦截触摸事件
     *
     * @param d
     */
    private void requestDisallowInterceptTouchEvent(boolean d) {
        ViewParent parent = getParent();
        if (parent != null) {
            parent.requestDisallowInterceptTouchEvent(d);
        }

    }

    /**
     * 计算按下的那个字母
     *
     * @return
     */
    private int getChoose(float y) {
        float dis = y - getPaddingTop();//按下的点到第一个字母的高度
        int choose = (int) (dis / letterHeight);//从0开始
        if (choose >= ARRAY.length) {
            choose = ARRAY.length - 1;
        } else if (choose < 0) {
            choose = 0;
        }
        return choose;
    }

    /**
     * 重置选择
     */
    public void resetChoose() {
        choose = -1;
        postInvalidate();
    }

    /**
     * 设置选中的字母
     *
     * @param letter
     */
    public void setChooser(String letter) {
        for (int i = 0; i < ARRAY.length; i++) {
            if (ARRAY[i].equalsIgnoreCase(letter)) {
                choose = i;
                postInvalidate();
                break;
            }
        }
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        baseLineOff = 0;
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        if (DEBUG) {
            LogUtils.e(TAG, "onMeasure:>>>>>>>>>>>>>>>>>widthSize=" + widthSize + ",heightSize=" + heightSize);
        }
        if (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY || widthSize <= 0) {
            //宽度不确定
//            widthSize = 100 + getPaddingStart() + getPaddingEnd();
            measureTextSize(heightSize, false);
            float minWidth = paint.measureText(M);
            widthSize = (int) (minWidth + getPaddingStart() + getPaddingEnd() + 5);
        }
        if (DEBUG) {
            LogUtils.d(TAG, "onMeasure:widthSize=" + widthSize);
            LogUtils.d(TAG, "onMeasure:heightSize=" + heightSize);
        }
        setMeasuredDimension(widthSize, heightSize);
        if (baseLineOff <= 0) {
            measureTextSize(heightSize, true);
        }
    }

    /**
     * 计算出文字大小
     *
     * @param height
     * @param limitWidth
     */
    private void measureTextSize(int height, boolean limitWidth) {
        //内容区域平分为每个文字的高度
        letterHeight = (height - getPaddingTop() - getPaddingBottom()) / ARRAY.length;
        if (textSize <= 0) {
            //计算字母大小
            textSize = letterHeight * 2 / 3;
        }
        if (DEBUG) {
//            LogUtils.d(TAG, "measureTextSize:letterHeight=" + letterHeight);
        }
        //文字大大小
        textSize = ensureTextSize(textSize, letterHeight, mFontMetrics, limitWidth);
        paint.setTextSize(textSize);
        baseLineOff = (mFontMetrics.descent + mFontMetrics.ascent) / 2;
        if (DEBUG) {
//            LogUtils.d(TAG, "measureTextSize:textSize=" + textSize);
//            LogUtils.d(TAG, "measureTextSize:baseLineOff=" + baseLineOff);
        }
    }

    /**
     * 确保文字的高度不大于最大高度,计算出最佳文字大小
     *
     * @param textSize
     * @param maxHeight
     * @param fontMetrics
     * @param limitWidth
     * @return
     */
    private int ensureTextSize(int textSize, int maxHeight, Paint.FontMetrics fontMetrics, boolean limitWidth) {
        if (DEBUG) {
//            LogUtils.d(TAG, "ensureTextSize:textSize=" + textSize+",maxHeight="+maxHeight);
        }
        paint.setTextSize(textSize);
        paint.getFontMetrics(fontMetrics);
        float textHeight = fontMetrics.descent - fontMetrics.ascent;
        if (!limitWidth) {
            if (DEBUG) {
//                LogUtils.d(TAG, "ensureTextSize:textHeight=" + textHeight);
            }
            if (textHeight > maxHeight) {
                return ensureTextSize(--textSize, maxHeight, fontMetrics, limitWidth);
            } else {
                return textSize;
            }
        } else {
            float textWidth = paint.measureText(M);
            int measuredWidth = getMeasuredWidth();
            if (DEBUG) {
//                LogUtils.d(TAG, "ensureTextSize:textHeight=" + textHeight);
//                LogUtils.d(TAG, "ensureTextSize:textWidth=" + textWidth);
//                LogUtils.d(TAG, "ensureTextSize:measuredWidth=" + measuredWidth);
            }
            if (textHeight > maxHeight || textWidth + getPaddingStart() + getPaddingEnd() > measuredWidth) {
                return ensureTextSize(--textSize, maxHeight, fontMetrics, limitWidth);
            } else {
                return textSize;
            }
        }

    }

    /**
     * 字母改变监听
     */
    public interface OnTouchingLetterChangedListener {
        void onTouchingLetterChanged(String letter);
    }

    public void setOnTouchingLetterChangedListener(OnTouchingLetterChangedListener listener) {
        this.listener = listener;
    }

    public void setAutoReset(boolean autoReset) {
        this.autoReset = autoReset;
    }
}
